/* 
 * Advanced Foundation Classes
 * Copyright (C) 2000/2004  Fabio Rotondo - Andrea Galimberti
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "../easygui.h"
#include "../widgets.h"
#include "../../dynamic_class.h"
#include "../../threader.h"

static const char class_name [] = "Drawing area test";


#define LIFEMAP_WIDTH 100
#define LIFEMAP_HEIGHT 100
#define LIFEMAP_POINT(px,py)    lifemap [ ( ( py ) * LIFEMAP_WIDTH ) + px ]
#define LIFEMAP_DOT_SIZE 2


int life_calc ( ThreaderData * td )
{
	EasyGUIWidgetData * ew = NULL;
	GtkWidget * w = NULL;
	DynamicClass * area = ( DynamicClass * ) td->info;
	int * lifemap = ( int * ) afc_dynamic_class_get_var ( area, "lifemap" );
	int x = 0;
	int y = 0;
	int sum = 0;
	int dx = 0;
	int dy = 0;
	int curr_value = 0;

	WIDGET_GET_EWIDGET ( area, ew );

	w = ew->gtk_handle;


	while (1) {
		if ( afc_threader_lock ( td, "now_drawing", TRUE ) == AFC_ERR_NO_ERROR ) {

			//printf ( "." );
			//fflush ( stdout );

			for ( y = 1; y < LIFEMAP_HEIGHT; y ++ ) {
				for ( x = 1; x < LIFEMAP_WIDTH ; x++ ) {
					sum = 0;
					curr_value = LIFEMAP_POINT ( x, y );

					for ( dy = -1; dy <= 1; dy ++ ) {
						for ( dx = -1; dx <= 1; dx ++ ) {
							if ( ( dx == 0 ) && ( dy == 0 ) ) sum = sum; //do nothing
							else sum += LIFEMAP_POINT ( x + dx, y + dy );
						} //dx
					} //dy

					if ( curr_value == 1 ) {
						if ( ( sum >= 4 ) || ( sum <= 1 ) ) LIFEMAP_POINT ( x, y ) = 0;
					}
					else {
						if ( sum == 3 ) LIFEMAP_POINT ( x, y ) = 1;
					}
				} //x
			} //y

			gdk_threads_enter ();
			gtk_widget_queue_draw_area ( w, 0, 0, w->allocation.width, w->allocation.height );
			//afc_dynamic_class_execute ( area, "invalidate_area", AFC_DYNAMIC_CLASS_ARG_END );
			gdk_threads_leave ();

			afc_threader_unlock ( td, "now_drawing" );

		} //if
	} //while

}

void draw_map_point ( DynamicClass * dyn, int state, int x, int y ) {

	switch ( state ) {
		case 1:
			afc_dynamic_class_execute ( dyn, "draw_rectangle", 0, true, x * LIFEMAP_DOT_SIZE, y * LIFEMAP_DOT_SIZE, LIFEMAP_DOT_SIZE, LIFEMAP_DOT_SIZE, AFC_DYNAMIC_CLASS_ARG_END );

			break;

		case 0:
			afc_dynamic_class_execute ( dyn, "draw_rectangle", 1, true, x * LIFEMAP_DOT_SIZE, y * LIFEMAP_DOT_SIZE, LIFEMAP_DOT_SIZE, LIFEMAP_DOT_SIZE, AFC_DYNAMIC_CLASS_ARG_END );

			break;

	} //switch

}
 
int da_expose ( DynamicClass * dc, EasyGUIContext * context )
{
	int * lifemap = ( int * ) afc_dynamic_class_get_var ( dc, "lifemap" );
	Threader * th = ( Threader * ) afc_dynamic_class_get_var ( dc, "threader" );
	ThreaderData * td = ( ThreaderData * ) afc_dictionary_get ( th->threads, "life_calc" );

	int x = 0;
	int y = 0;

	if ( afc_threader_lock ( td, "now_drawing", TRUE ) == AFC_ERR_NO_ERROR ) {

		//printf ( "o" );
		//fflush ( stdout );

		for ( y = 0; y < LIFEMAP_HEIGHT; y ++ ) {
			for ( x = 0; x < LIFEMAP_WIDTH; x ++ ) {

				draw_map_point ( dc, LIFEMAP_POINT ( x, y ), x, y );

			}
		}

		afc_threader_unlock ( td, "now_drawing" );
	} //if


	return ( 0 );
}

/*************
     MAIN
*************/

int main ( int argc, char * argv[] )
{
	AFC * afc = afc_new (); 
	EasyGUI * easygui = afc_easygui_new ();
	EasyGUIContext * context;
	int afc_res = 0;
	Threader * calc_thread = afc_threader_new ();

	DynamicClass * area = NULL;
	int * lifemap = NULL;
	int x = 0;
	int y = 0;

	if ( ( lifemap = afc_malloc ( LIFEMAP_WIDTH * LIFEMAP_HEIGHT * sizeof ( int ) ) ) == NULL ) {
		fprintf ( stderr, "lifemap malloc failed.\n" );
		return ( 1 );
	}
	else {
		for ( y = 0; y < LIFEMAP_HEIGHT; y++ ) {
			for ( x = 0; x < LIFEMAP_WIDTH; x++ ) {
				if ( ( 1 + ( int ) ( 1000.0 * rand () / ( RAND_MAX + 1.0 ) ) ) < 900 )
					LIFEMAP_POINT ( x, y ) = 0;
				else
					LIFEMAP_POINT ( x, y ) = 1;
			}
		}
	}

	if ( easygui == NULL ) 
	{
	  fprintf ( stderr, "Init of class EasyGUI failed.\n" );
	  return ( 1 );
	}

	if ( calc_thread == NULL )
	{
	  fprintf ( stderr, "Init of class Threader failed.\n" );
	  return ( 1 );
	}

	g_thread_init ( NULL );
	gdk_threads_init ();
	afc_easygui_init ( easygui );

	context = afc_easygui_add_context ( easygui, NULL );

	afc_easygui_context_set_gui_from_file ( context, "gui_draw.egui" );

	//afc->debug_level = AFC_DEBUG_EVERYTHING; 

	if ( ( afc_res = afc_easygui_context_show ( context ) ) != AFC_ERR_NO_ERROR ) {
		fprintf ( stderr, "res: %x\n", afc_res );
	}
	else {
		area = afc_easygui_context_get_widget ( context, "da" );
		afc_dynamic_class_set_var ( area, AFC_DYNAMIC_CLASS_VAR_KIND_POINTER, "lifemap", lifemap );

		afc_threader_add ( calc_thread, "life_calc", (ThreaderFunc) life_calc, area );
		afc_dynamic_class_set_var ( area, AFC_DYNAMIC_CLASS_VAR_KIND_POINTER, "threader", calc_thread );

		gdk_threads_enter ();
		afc_easygui_main ( easygui );
		gdk_threads_leave ();
	}

	afc_threader_cancel ( calc_thread, "life_calc" );

	afc_threader_wait ( calc_thread );

	afc_threader_delete ( calc_thread );

	afc_easygui_delete ( easygui );

	afc_delete ( afc );

	if ( lifemap ) afc_free ( lifemap );

	return ( 0 ); 
}
